package com._1.message.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

@Component
public class CustomRedisLock {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    /**
     * 尝试获取锁
     * @param lockKey
     * @param requestId
     * @param expireTime
     * @return
     */
    public boolean tryLock(String lockKey, String requestId, long expireTime){
        Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, requestId,expireTime, TimeUnit.MILLISECONDS);
        return  result !=null && result;
    }

    /**
     * 非原子性删除
     * @param lockKey
     * @param requestId
     * @return
     */
    public boolean releaseLockNonAtomic(String lockKey, String requestId){
        String currentValue = redisTemplate.opsForValue().get(lockKey);
        if(currentValue != null && currentValue.equals(requestId)){
            return redisTemplate.opsForValue().getOperations().delete(lockKey);
        }
        return false;
    }

    /**
     * 原子性删除
     *
     * if redis.call('get', KEYS[1]) == ARGV[1] then
     *     return redis.call('del', KEYS[1])
     * else
     *     return 0
     * end
     *
     * @param lockKey
     * @param requestId
     * @return
     */
    public boolean releaseLockAtomic(String lockKey, String requestId){
        // 使用 Lua 脚本确保释放锁的原子性
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(script);
        redisScript.setResultType(Long.class);
        Long result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), requestId);
        return result != null && result == 1L;
    }


}
